﻿/*******************************************************************
Copyright (c) 2011 이재범

*  Permission is hereby granted, free of charge, to any person
*  obtaining a copy of this software and associated documentation
*  files (the "Software"), to deal in the Software without
*  restriction, including without limitation the rights to use,
*  copy, modify, merge, publish, distribute, sublicense, and/or sell
*  copies of the Software, and to permit persons to whom the
*  Software is furnished to do so, subject to the following
*  conditions:
* 
*  The above copyright notice and this permission notice shall be
*  included in all copies or substantial portions of the Software.
* 
*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
*  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
*  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
*  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
*  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
*  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
*  OTHER DEALINGS IN THE SOFTWARE.
*******************************************************************/

#include "equation.h"
#include "exception.h"
#include "common.h"
#include <ctype.h>

bool Equation::is_operator(int i, string &operator_name)
{
	operator_name.clear();

	string check_operator_name; // exponent_1 의 경우 exponent 만 들어간다. 

	// 현재 i 는 \ 를 가리키고 있음
	int j;

	for(j = i + 1; j < static_cast<int>(equation.length()); j++)
	{
		if(!(is_alpha(equation[j]) || is_digit(equation[j]) || equation[j] == '_' || equation[j] == '@'))
			break;
		if(is_alpha(equation[j]))
			check_operator_name.push_back(equation[j]);
		operator_name.push_back(equation[j]);
	}

	if(non_operator_list.find(operator_name) == -1) // non_operator_list 에서 찾지 못했다면
		return true;
	else // 찾았다면
		return false;

}
bool Equation::is_operator_only_for_subscript(int i, string &operator_name)
{
	operator_name.clear();

	string check_operator_name;

	// 현재 i 는 \ 를 가리키고 있음
	int j;

	for(j = i + 1; j < static_cast<int>(equation.length()); j++)
	{
		if(!(is_alpha(equation[j]) || is_digit(equation[j])))
			break;
		if(is_alpha(equation[j]))
			check_operator_name.push_back(equation[j]);
		operator_name.push_back(equation[j]);
	}

	if(non_operator_list.find(operator_name) == -1) // non_operator_list 에서 찾지 못했다면
		return true;
	else // 찾았다면
		return false;

}
bool Equation::is_equal_related_operator(string& operator_name)
{
	if(equal_symbol_list.find(operator_name) != -1)
		return true;
	else
		return false; 
}
bool Equation::is_binary_operator(string &operator_name)
{
	if(binary_operator_list.find(operator_name) == -1)
		return false;
	else
		return true;
}
bool Equation::is_dot(string &operator_name)
{
	if(dot_symbol_list.find(operator_name) == -1)
		return false;
	return true;
}
bool Equation::is_changeable(string &operator_name)
{
	if(changeable_operator_list.find(operator_name) != -1 || equal_symbol_list.find(operator_name) != -1
		|| operator_name == "plus" || operator_name == "comma")
	{
		return true;
	}
	return false;
}
bool Equation::is_unchangeable(string &operator_name)
{
	if(unchangeable_operator_list.find(operator_name) == -1)
		return false;

	return true;

}
bool Equation::is_two_parameter_operator(string &operator_name)
{
	if(is_binary_operator(operator_name) || is_equal_related_operator(operator_name) || operator_name == "comma" )
		return true;
	else
		return false;

	return false;
}
bool Equation::is_operator(string& equation, int i, string& operator_name)
{
	operator_name.clear();

	string check_operator_name; // exponent_1 의 경우 exponent 만 들어간다. 

	// 현재 i 는 \ 를 가리키고 있음
	int j;

	for(j = i + 1; j < static_cast<int>(equation.length()); j++)
	{
		if(!(is_alpha(equation[j]) || is_digit(equation[j]) || equation[j] == '_' || equation[j] == '@'))
			break;
		if(is_alpha(equation[j]))
			check_operator_name.push_back(equation[j]);
		operator_name.push_back(equation[j]);
	}

	if(non_operator_list.find(operator_name) == -1) // non_operator_list 에서 찾지 못했다면
		return true;
	else // 찾았다면
		return false;
}
bool Equation::is_keyword_operand(string &operator_name)
{
	if(operand_as_keyword.find(operator_name) == -1)
		return false;

	return true;
}

void Equation::optimize_space()
{
	int i = 0;
	while (i < static_cast<int>(equation.length()))
	{
		if(equation[i] == ' ')
		{
			equation.erase(i, 1);
			continue;
		}
		i++;
	}
}
void Equation::optimize_parenth()
{
	int location = 0;

	while (location < static_cast<int>(equation.length()) )
	{
		if(equation[location] == '{' || equation[location] == '(')
		{
			int find = location;
			bool is_left_braket_alone = false;

			// 현재 find 에는 내가 찾은 중괄호의 위치가 저장되어 있으므로
			// 1 을 빼준다. 

			find --;
			while (find >= 0)
			{
				if(equation[find] == '{' || equation[find] == '(')
				{
					is_left_braket_alone = true;
					break;
				}
				else if(equation[find] == ' ')
				{
					find --;
					continue;
				}
				else
					break;
			}

			if(is_left_braket_alone)
			{
				// 먼저 오른쪽 괄호를 찾는다.
				int count = 0;
				find = location;

				while (find < static_cast<int>(equation.length()) )
				{
					if(equation[find] == '{' || equation[find] == '(')
						count ++;
					else if(equation[find] == '}' || equation[find] == ')')
						count --;

					if(count == 0)
						break;

					find ++;
				}

				// 현재 find 에는 내가 찾은 } 의 위치가 저장되어 있음
				int right_braket_loc = find;

				find ++;
				// 오른쪽 괄호 부터 } 다음에 바로 } 가 연속되어 나오는지 확인
				while (find < static_cast<int>(equation.length()) )
				{
					if(equation[find] == '}' || equation[find] == ')')
					{
						equation.erase(right_braket_loc, 1);
						equation.erase(location, 1);
						location --; 
						break;
					}
					else if(equation[find] == ' ')
					{
						find ++;
						continue;
					}
					else
						break;
				}
			}
		}
		location ++;
	}
}
void Equation::get_symbol_name(int i, string& operator_name)
{
	operator_name.clear();

	string check_operator_name; // exponent_1 의 경우 exponent 만 들어간다. 
	// 현재 i 는 \ 를 가리키고 있음
	int j;

	for(j = i + 1; j < static_cast<int>(equation.length()); j++)
	{
		if(!(is_alpha(equation[j]) || is_digit(equation[j]) || equation[j] == '_' || equation[j] == '@'))
			break;
		if(is_alpha(equation[j]))
			check_operator_name.push_back(equation[j]);
		operator_name.push_back(equation[j]);
	}
}
int Equation::find_match_parenth(int i)
{
	int j, count = 0;
	int equation_length = equation.length();

	if(equation[i] == '(' || equation[i] == '{'  || equation[i] == '[')
	{
		for(j = i + 1; j < equation_length; j++)
		{
			if(equation[j] == '(' || equation[j] == '{' || equation[j] == '[')
				count ++;
			else if(equation[j] == ')' || equation[j] == '}' || equation[j] == ']')
				count --;

			if(count == -1)
				return j;
		}
	}
	else if(equation[i] == ')' || equation[i] == '}' || equation[i] == ']' )
	{
		for(j = i - 1; j >= 0; j--)
		{
			if(equation[j] == '(' || equation[j] == '{' || equation[j] == '[')
				count ++;
			else if(equation[j] == ')' || equation[j] == '}' || equation[j] == ']')
				count --;

			if(count == 1)
				return j;
		}
	}
	
	return -1; // 애러
}